const std = @import("std");
const stdin = std.io.getStdIn();
const stdout = std.io.getStdOut().writer();
const expect = @import("std").testing.expect;

const User = struct {
    id: u64,
    name: []const u8,
    email: []const u8,

    fn init(id: u64, name: []const u8, email: []const u8) User {
        return User{ .id = id, .name = name, .email = email };
    }

    fn print_name(self: User) !void {
        try stdout.print("{s}\n", .{self.name});
    }
};

fn demo() !void {
    // ############################
    //这里添加测试的代码
    const number: u8 = 5;
    // &运算符在 Zig 中创建一个指针对象
    const pointer = &number;
    const doubled = 2 * pointer.*;
    std.debug.print("{d}\n", .{doubled});
}

fn demo2() !void {
    var number: u8 = 5;
    const pointer = &number;
    pointer.* = 6;
    try stdout.print("{d}\n", .{number});
}

fn demo3() !void {
    const u = User.init(1, "pedro", "email@gmail.com");
    const pointer = &u;
    try pointer.*.print_name();
}

fn demo4() !void {
    var number: u8 = 5;
    const pointer = &number;
    pointer.* = 7;
    try stdout.print("{d}\n", .{number});
}

fn demo5() !void {
    const c1: u8 = 5;
    const c2: u8 = 6;
    var pointer = &c1;
    try stdout.print("{d}\n", .{pointer.*});
    pointer = &c2;
    try stdout.print("{d}\n", .{pointer.*});
}

fn demo6() !void {
    try stdout.print("Start: {s}!\n", .{"demo6"});
    const ar = [_]i32{ 1, 2, 3, 4 };
    var ptr: [*]const i32 = &ar;
    try stdout.print("{d}\n", .{ptr[0]});
    ptr += 1;
    try stdout.print("{d}\n", .{ptr[0]});
    ptr += 1;
    try stdout.print("{d}\n", .{ptr[0]});
}

fn demo7() !void {
    try stdout.print("Start: {s}!\n", .{"demo7"});
    const ar = [_]i32{ 1, 2, 3, 4 };
    const sl = ar[0..ar.len];
    for (sl, 0..) |character, index| {
        try stdout.print(
            "Result: index {d} value {d} !\n",
            .{
                index,
                character,
            },
        );
    }
}

fn demo8() !void {
    try stdout.print("Start: {s}!\n", .{"demo8"});
    // 使用 if 语句时，需要使用一对竖线符号来解包可选值，并在 if 语句块中使用这个“解包后的对象”。
    // 如果对象num为 null，则 if 语句中的代码不会被执行，否则，if 语句会将解包后的对象返回num到该not_null_num对象中。
    // 在 if 语句的范围内，该not_null_num对象保证不为 null
    const num: ?i32 = 5;
    if (num) |not_null_num| {
        try stdout.print("{d}\n", .{not_null_num});
    }
    // 由于 x 对象当前为空，因此orelse决定使用替代值，即数字 15。
    const x: ?i32 = null;
    const dbl = (x orelse 15) * 2;
    try stdout.print("{d}\n", .{dbl});
}

pub fn main() !void {
    try stdout.print("Result: {s}!\n", .{"hello world"});
    // 从标准输入中接收用户输入
    // const input_reader = stdin.reader();
    // _ = try input_reader.readUntilDelimiterOrEof(input, '\n');
    // std.debug.print("{s}\n", .{input});
    try demo2();
    try demo3();
    try demo4();
    try demo5();
    try demo6();
    try demo7();
    try demo8();

    var num: ?i32 = 5;
    num = null;

    // ############################
}

test "test main" {
    const n = 8;
    try stdout.print("Result: {d}!\n", .{n});
}
